﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Vit.Common.Extensions;
using VitData = Vit.Web.DataAnnotations;

namespace Vit.CMS.Data
{
    [MetadataType(typeof(ControlLoaderInfoMetaData))]
    public class ControlLoaderInfo : Vit.Common.IStringSerializable
    {
        public ControlLoaderInfo(PageInfo pageInfo, object parent)
        {
            UrlReplaceWithUserProfile = false;
            UrlReplaceWithRouteData = false;
            LoadOnce = false;

            ContentReplaces = new List<ContentReplaceInfo>();
            PlaceHolders = new List<string>();

            PageInfo = pageInfo;
            Parent = parent;
        }

        public string Url { get; set; }
        public bool UrlReplaceWithUserProfile { get; set; }
        public bool UrlReplaceWithRouteData { get; set; }
        public bool LoadOnce { get; set; }
        public string ID { get; set; }
        public int Indent { get; set; }

        public List<ContentReplaceInfo> ContentReplaces { get; set; }
        public List<string> PlaceHolders { get; set; }
        public string FilePath { get; set; }
        public string Content { get; set; }

        public PageInfo PageInfo { get; private set; }
        public object Parent { get; private set; }

        #region IStringSerializable Members

        public string Serialize()
        {
            string content = "";

            foreach (ContentReplaceInfo cri in this.ContentReplaces)
            {
                cri.Indent = Indent + 1;
                content += cri.Serialize();
                content += "\r\n";
            }

            string html = string.Format(@"{0}<vit:ControlLoader ID=""{1}"" runat=""server"" Url=""{2}"" UrlReplaceWithUserProfile=""{3}"" UrlReplaceWithRouteData=""{4}"" LoadOnce=""{5}"">
{6}
{0}</vit:ControlLoader>", "\t".Repeat(Indent),
                ID, Url, UrlReplaceWithUserProfile, UrlReplaceWithRouteData, LoadOnce, content.TrimEnd());

            return html;
        }

        public void Deserialize(string value)
        {
            string ns = "vit:ControlLoader";
            string pattern = string.Format(@"<{0}\s*(?<attributes>[^<>]*?)\s*((/>)|(>(?<content>(.|\r|\n)*?)</{0}>))", ns);
            Match match = null;
            RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline;

            string attibutes = "";
            match = Regex.Match(value, pattern, options);
            if (match.Success)
            {
                attibutes = match.Groups["attributes"].Value.Trim();
                this.Content = match.Groups["content"].Value.Trim();
            }

            pattern = @"ID\s*=\s*""(?<content>[^<>]+?)""";
            match = Regex.Match(attibutes, pattern, options);
            if (match.Success)
                this.ID = match.Groups["content"].Value.Trim();

            pattern = @"Url\s*=\s*""(?<content>[^<>]+?)""";
            match = Regex.Match(attibutes, pattern, options);
            if (match.Success)
                this.Url = match.Groups["content"].Value.Trim();

            pattern = @"UrlReplaceWithUserProfile\s*=\s*""(?<content>(true|false))""";
            match = Regex.Match(attibutes, pattern, options);
            if (match.Success)
                this.UrlReplaceWithUserProfile = Boolean.Parse(match.Groups["content"].Value.Trim());

            pattern = @"UrlReplaceWithRouteData\s*=\s*""(?<content>(true|false))""";
            match = Regex.Match(attibutes, pattern, options);
            if (match.Success)
                this.UrlReplaceWithRouteData = Boolean.Parse(match.Groups["content"].Value.Trim());

            pattern = @"LoadOnce\s*=\s*""(?<content>(true|false))""";
            match = Regex.Match(attibutes, pattern, options);
            if (match.Success)
                this.LoadOnce = Boolean.Parse(match.Groups["content"].Value.Trim());

            if (!string.IsNullOrEmpty(this.Content))
            {
                pattern = @"<vit:ContentReplace[^<>]*?((/>)|(>(.|\r|\n)*?</vit:ContentReplace>))";
                MatchCollection matches = Regex.Matches(this.Content, pattern, options);

                foreach (Match m in matches)
                {
                    ContentReplaceInfo cri = new ContentReplaceInfo(PageInfo, this);
                    cri.Deserialize(m.Value);
                    this.ContentReplaces.Add(cri);
                }
            }

            string file = this.Url;
            if (UrlReplaceWithUserProfile)
                file = Vit.Web.Helpers.URLHelper.ReplaceWithUserProfile(file);
            if (UrlReplaceWithRouteData)
                file = Vit.Web.Helpers.URLHelper.ReplaceWithRouteData(file);

            file = HttpContext.Current.Server.MapPath(file);
            if (File.Exists(file))
            {
                StreamReader sr = new StreamReader(file);
                string loaderContent = sr.ReadToEnd();
                sr.Close();

                if (!string.IsNullOrEmpty(loaderContent))
                {
                    pattern = (@"<asp:PlaceHolder[^<>]*ID\s*=\s*""(?<id>[^<>]+?)""[^<>]*?((/>)|(>(.|\r|\n)*?</asp:PlaceHolder>))");
                    MatchCollection matches = Regex.Matches(loaderContent, pattern, options);
                    foreach (Match m in matches)
                    {
                        this.PlaceHolders.Add(m.Groups["id"].Value.Trim());
                    }
                }
            }
        }

        #endregion

        public class ControlLoaderInfoMetaData
        {
            [VitData.DisplayName("ControlLoaderInfo.Url")]
            public string Url { get; set; }
            [VitData.DisplayName("ControlLoaderInfo.UrlReplaceWithUserProfile")]
            public bool UrlReplaceWithUserProfile { get; set; }
            [VitData.DisplayName("ControlLoaderInfo.UrlReplaceWithRouteData")]
            public bool UrlReplaceWithRouteData { get; set; }
            [VitData.DisplayName("ControlLoaderInfo.LoadOnce")]
            public bool LoadOnce { get; set; }
            [VitData.DisplayName("ControlLoaderInfo.ID")]
            public string ID { get; set; }
            [ScaffoldColumn(false)]
            public int Indent { get; set; }

            [VitData.DisplayName("ControlLoaderInfo.ContentReplaces")]
            [UIHint("ContentReplaces")]
            public List<ContentReplaceInfo> ContentReplaces { get; set; }
            [VitData.DisplayName("ControlLoaderInfo.PlaceHolders")]
            [UIHint("PlaceHolders")]
            public List<string> PlaceHolders { get; set; }

            [ScaffoldColumn(false)]
            public string FilePath { get; set; }
            [ScaffoldColumn(false)]
            public string Content { get; set; }

            [ScaffoldColumn(false)]
            public PageInfo PageInfo { get; private set; }
            [ScaffoldColumn(false)]
            public object Parent { get; private set; }
        }
    }
}
